home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / mpeg_play-2.1 / gdith.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  24KB  |  1,026 lines

  1. /* 
  2.  * gdith.c --
  3.  *
  4.  *      Procedures dealing with grey-scale and mono dithering, 
  5.  *      as well as X Windows set up procedures.
  6.  *
  7.  */
  8.  
  9. /*
  10.  * Copyright (c) 1995 The Regents of the University of California.
  11.  * All rights reserved.
  12.  * 
  13.  * Permission to use, copy, modify, and distribute this software and its
  14.  * documentation for any purpose, without fee, and without written agreement is
  15.  * hereby granted, provided that the above copyright notice and the following
  16.  * two paragraphs appear in all copies of this software.
  17.  * 
  18.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  19.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  20.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  21.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22.  * 
  23.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  24.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  25.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  26.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  27.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  28.  */
  29.  
  30. #include <math.h>
  31. #include "video.h"
  32. #include "proto.h"
  33. #include "dither.h"
  34. #include <sys/time.h>
  35.  
  36. /* Range values for lum, cr, cb. */
  37. int LUM_RANGE;
  38. int CR_RANGE;
  39. int CB_RANGE;
  40.  
  41. /* Array that remaps color numbers to actual pixel values used by X server. */
  42.  
  43. unsigned char pixel[256];
  44. unsigned long wpixel[256];
  45.  
  46. /* Arrays holding quantized value ranged for lum, cr, and cb. */
  47.  
  48. int *lum_values;
  49. int *cr_values;
  50. int *cb_values;
  51.  
  52. /* Declaration of global variable containing dither type. */
  53.  
  54. extern int ditherType;
  55. extern int matched_depth;
  56.  
  57. /* Structures used by the X server. */
  58.  
  59. Display *display;
  60.  
  61. static XImage *ximage = NULL;
  62. static Colormap cmap;
  63. static Window window;
  64. static GC gc;
  65.  
  66. /* Frame Rate Info */
  67. extern int framerate;
  68.  
  69. /* Video rates table */
  70. /* Cheat on Vid rates, round to 30, and use 30 if illegal value 
  71.    Except for 9, where Xing means 15, and given their popularity, we'll
  72.    be nice and do it */
  73. static int VidRateNum[16]={30, 24, 24, 25, 30, 30, 50, 60, 
  74.                          60, 15, 30, 30, 30, 30, 30, 30};
  75.  
  76. /* Luminance and chrominance lookup tables */
  77. static double *L_tab, *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
  78.  
  79.  
  80. /*
  81.  *--------------------------------------------------------------
  82.  *
  83.  * InitColor --
  84.  *
  85.  *    Initialize lum, cr, and cb quantized range value arrays.
  86.  *      Also initializes the lookup tables for the possible
  87.  *      values of lum, cr, and cb.
  88.  *
  89.  * Results: 
  90.  *      None.
  91.  *
  92.  * Side effects:
  93.  *      None.
  94.  *
  95.  *--------------------------------------------------------------
  96.  */
  97.  
  98. void
  99. InitColor()
  100. {
  101.   int i, CR, CB;
  102.  
  103.   L_tab    = (double *)malloc(LUM_RANGE*sizeof(double)); 
  104.   Cr_r_tab = (double *)malloc(CR_RANGE*sizeof(double));
  105.   Cr_g_tab = (double *)malloc(CR_RANGE*sizeof(double));
  106.   Cb_g_tab = (double *)malloc(CB_RANGE*sizeof(double));
  107.   Cb_b_tab = (double *)malloc(CB_RANGE*sizeof(double));
  108.  
  109.   if (gammaCorrectFlag) {
  110.     for (i=0; i<LUM_RANGE; i++) {
  111.       lum_values[i] = ((i * 256) / (LUM_RANGE)) + (256/(LUM_RANGE*2));
  112.       L_tab[i] = 1.164 * (lum_values[i] - 16.0);
  113.       L_tab[i] = (pow(L_tab[i] / 255.0, (1 / gammaCorrect)) * 255.0) + 0.5;
  114.     }
  115.   } else {
  116.     for (i=0; i<LUM_RANGE; i++) {
  117.       lum_values[i] = ((i * 256) / (LUM_RANGE)) + (256/(LUM_RANGE*2));
  118.       L_tab[i] = 1.164 * (lum_values[i] - 16.0);
  119.     }
  120.   }
  121.  
  122.   for (i=0; i<CR_RANGE; i++) {
  123.     cr_values[i] = ((i * 256) / (CR_RANGE)) + (256/(CR_RANGE*2));
  124.     Cr_r_tab[i] = 1.366 * (cr_values[i] - 128.0);
  125.     Cr_g_tab[i] = -0.700 * (cr_values[i] - 128.0);
  126.   }
  127.  
  128.   for (i=0; i<CB_RANGE; i++) {
  129.     cb_values[i] = ((i * 256) / (CB_RANGE)) + (256/(CB_RANGE*2));
  130.     Cb_g_tab[i] = -0.334 * (cb_values[i] - 128.0);
  131.     Cb_b_tab[i] = 1.732 * (cb_values[i] - 128.0);
  132.   }
  133.  
  134. }
  135.  
  136.  
  137. /*
  138.  *--------------------------------------------------------------
  139.  *
  140.  * ConvertColor --
  141.  *
  142.  *    Given a l, cr, cb tuple, converts it to r,g,b.
  143.  *
  144.  * Results:
  145.  *    r,g,b values returned in pointers passed as parameters.
  146.  *
  147.  * Side effects:
  148.  *      None.
  149.  *
  150.  *--------------------------------------------------------------
  151.  */
  152.  
  153. static void
  154. ConvertColor(l, cr, cb, r, g, b)
  155.      unsigned int l, cr, cb;
  156.      unsigned char *r, *g, *b;
  157. {
  158.   double fl, fcr, fcb, fr, fg, fb;
  159.  
  160. /*
  161.  * Old method w/o lookup table
  162.  *
  163.  * fl = 1.164*(((double) l)-16.0);
  164.  * fcr =  ((double) cr) - 128.0;
  165.  * fcb =  ((double) cb) - 128.0;
  166.  *
  167.  * fr = fl + (1.366 * fcr);
  168.  * fg = fl - (0.700 * fcr) - (0.334 * fcb);
  169.  * fb = fl + (1.732 * fcb);
  170.  */
  171.  
  172.   fl = L_tab[l];
  173.  
  174.   fr = fl + Cr_r_tab[cr];
  175.   fg = fl + Cr_g_tab[cr] + Cb_g_tab[cb];
  176.   fb = fl + Cb_b_tab[cb];
  177.  
  178.   if (fr < 0.0) fr = 0.0;
  179.   else if (fr > 255.0) fr = 255.0;
  180.  
  181.   if (fg < 0.0) fg = 0.0;
  182.   else if (fg > 255.0) fg = 255.0;
  183.  
  184.   if (fb < 0.0) fb = 0.0;
  185.   else if (fb > 255.0) fb = 255.0;
  186.  
  187.   *r = (unsigned char) fr;
  188.   *g = (unsigned char) fg;
  189.   *b = (unsigned char) fb;
  190.  
  191. }
  192.  
  193. #ifdef SH_MEM
  194.  
  195. int gXErrorFlag = 0;
  196.  
  197. int HandleXError(dpy, event)
  198.      Display *dpy;
  199.      XErrorEvent *event;
  200. {
  201.   gXErrorFlag = 1;
  202.  
  203.   return 0;
  204. }
  205.  
  206. int HandleXError();
  207.  
  208. void InstallXErrorHandler()
  209. {
  210.   XSetErrorHandler(HandleXError);
  211.   XFlush(display);
  212. }
  213.  
  214. void DeInstallXErrorHandler()
  215. {
  216.   XSetErrorHandler(NULL);
  217.   XFlush(display);
  218. }
  219. #endif
  220.  
  221.  
  222. /*
  223.  *--------------------------------------------------------------
  224.  *
  225.  * ResizeDisplay --
  226.  *
  227.  *    Resizes display window.
  228.  *
  229.  * Results:
  230.  *    None.
  231.  *
  232.  * Side effects:
  233.  *      None.
  234.  *
  235.  *--------------------------------------------------------------
  236.  */
  237.  
  238. void ResizeDisplay(w, h)
  239.      unsigned int w, h;
  240. {
  241.  
  242.   if (ditherType == NO_DITHER || ditherType == PPM_DITHER) return;
  243.  
  244.   XResizeWindow(display, window, w, h);
  245.   XFlush(display);
  246. }
  247.  
  248.  
  249. /*
  250.  *--------------------------------------------------------------
  251.  *
  252.  * MakeWindow --
  253.  *
  254.  *    Create X Window
  255.  *
  256.  * Results:
  257.  *    Read the code.
  258.  *
  259.  * Side effects:
  260.  *      None.
  261.  *
  262.  *--------------------------------------------------------------
  263.  */
  264.  
  265. #ifdef SH_MEM
  266. int CompletionType = -1;
  267. #endif
  268.  
  269. static int
  270. MakeWindow(name) 
  271. char *name;
  272. {
  273.   
  274.   XSizeHints hint;
  275.   unsigned int fg, bg;
  276.   char *hello = "MPEG Play";
  277.   int screen;
  278.   Window CreateFullColorWindow();
  279.   XVisualInfo vinfo;
  280.   
  281.   if ((ditherType == NO_DITHER) || (ditherType == PPM_DITHER)) return;
  282.  
  283.   display = XOpenDisplay(name);
  284.   if (display == NULL) {
  285.     fprintf(stderr, "Can not open display\n");
  286.     exit(-2);
  287.   }
  288.  
  289. #ifdef SH_MEM
  290.   if(shmemFlag)
  291.     CompletionType = XShmGetEventBase(display) + ShmCompletion;
  292. #endif
  293.  
  294.   screen = DefaultScreen (display);
  295.   
  296.   /* Fill in hint structure */
  297.  
  298.   hint.x = 200;
  299.   hint.y = 300;
  300.   hint.width = 150;
  301.   hint.height = 150;
  302.   hint.flags = PPosition | PSize;
  303.   
  304.   /* Get some colors */
  305.   
  306.   bg = WhitePixel (display, screen);
  307.   fg = BlackPixel (display, screen);
  308.   
  309.   /* Make the window */
  310.   
  311.   if (ditherType == FULL_COLOR_DITHER || ditherType == FULL_COLOR2_DITHER) {
  312.     window = CreateFullColorWindow (display, hint.x, hint.y, hint.width, hint.height);
  313.     if (window == 0) {
  314.       fprintf (stderr, "-color option only valid on full color display\n");
  315.       exit (-1);
  316.     }
  317.   } else {
  318.     if (((XMatchVisualInfo (display, screen, 24, TrueColor,   &vinfo) != 0) ||
  319.      (XMatchVisualInfo (display, screen, 24, DirectColor, &vinfo) != 0)) &&
  320.     (!quietFlag)) {
  321.       printf("\nOn 24 bit displays:  use -dither color to get full color\n\t\tordered dither is the default.\n");
  322.     }
  323.     if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
  324.       window = XCreateSimpleWindow (display,
  325.                     DefaultRootWindow (display),
  326.                     hint.x, hint.y,
  327.                     hint.width, hint.height,
  328.                     4, fg, bg);
  329.       matched_depth = 1;
  330.     } else {
  331.       Visual *vis;
  332.       XSetWindowAttributes attrib;
  333.       unsigned long attrib_flags=0;
  334.       
  335.       if (!XMatchVisualInfo (display, screen, matched_depth = 8, PseudoColor, 
  336.                  &vinfo)) {
  337.     if (ditherType != GRAY_DITHER && ditherType != GRAY2_DITHER &&
  338.         ditherType != GRAY256_DITHER && ditherType != GRAY2562_DITHER) {
  339.       fprintf(stderr, "specified dither requires 8 bit display\n");
  340.       return 0;
  341.     } else if (!XMatchVisualInfo(display, screen, matched_depth = 32,
  342.             GrayScale, &vinfo) &&
  343.                !XMatchVisualInfo(display, screen, matched_depth = 24,
  344.             GrayScale, &vinfo) &&
  345.                !XMatchVisualInfo(display, screen, matched_depth = 16,
  346.             GrayScale, &vinfo) &&
  347.                !XMatchVisualInfo(display, screen, matched_depth = 8,
  348.             GrayScale, &vinfo) &&
  349.                !XMatchVisualInfo(display, screen, matched_depth = 32,
  350.             TrueColor, &vinfo) &&
  351.                !XMatchVisualInfo(display, screen, matched_depth = 24,
  352.             TrueColor, &vinfo) &&
  353.                !XMatchVisualInfo(display, screen, matched_depth = 16,
  354.             TrueColor, &vinfo)) {
  355.       fprintf(stderr, "- -dither gray requires at least 8 bit display\n");
  356.       exit(-1);
  357.     }
  358.       }
  359.       
  360.       vis=vinfo.visual;
  361.       if (XDefaultDepthOfScreen(XDefaultScreenOfDisplay(display)) != 8) {
  362.     attrib_flags |= CWColormap;
  363.     attrib.colormap = XCreateColormap(display, DefaultRootWindow(display),
  364.                       vis, AllocNone);
  365.     owncmFlag = TRUE; 
  366.       }
  367.       
  368.       attrib.background_pixel = bg;
  369.       attrib.border_pixel = fg;
  370.       attrib.backing_store = NotUseful;
  371.       attrib.save_under = False;
  372.       attrib.background_pixel = bg;
  373.       attrib.border_pixel = bg;
  374.       attrib_flags |= CWBackPixel | CWBorderPixel | CWBackingStore | CWSaveUnder;
  375.       window = XCreateWindow (display,
  376.                   DefaultRootWindow (display),
  377.                   hint.x, hint.y,
  378.                   hint.width, hint.height, 4,
  379.                   matched_depth, InputOutput, vis,
  380.                   attrib_flags, &attrib);
  381.     }}
  382.   
  383.   XSelectInput(display, window, StructureNotifyMask);
  384.   
  385.   /* Tell other applications about this window */
  386.   
  387.   XSetStandardProperties (display, window, hello, hello, None, NULL, 0, &hint);
  388.   
  389.   /* Map window. */
  390.   
  391.   XMapWindow(display, window);
  392.   
  393.   /* Wait for map. */
  394.   while(1) {
  395.     XEvent    xev;
  396.     
  397.     XNextEvent(display, &xev);
  398.     if(xev.type == MapNotify && xev.xmap.event == window)
  399.       break;
  400.   }
  401.   
  402.   XSelectInput(display, window, NoEventMask);
  403.  
  404.   return TRUE;
  405. }
  406.   
  407.  
  408. /*
  409.  *--------------------------------------------------------------
  410.  *
  411.  * InitDisplay --
  412.  *
  413.  *    Initialized display, sets up colormap, etc.
  414.  *
  415.  * Results:
  416.  *      None.
  417.  *
  418.  * Side effects:
  419.  *      None.
  420.  *
  421.  *--------------------------------------------------------------
  422.  */
  423.  
  424. void InitDisplay(name)
  425. char *name;
  426. {
  427.  
  428.   int ncolors = LUM_RANGE*CB_RANGE*CR_RANGE;
  429.   XColor xcolor;
  430.   int i, lum_num, cr_num, cb_num;
  431.   unsigned char r, g, b;
  432.   Colormap dcmap;
  433.  
  434.   if ((ditherType == NO_DITHER) || (ditherType == PPM_DITHER)) return;
  435.   if (noDisplayFlag) return;
  436.  
  437.   if (!MakeWindow(name)) {
  438.     /* Could not do that dither.  Try again if can */
  439.     switch (ditherType) {
  440.     case HYBRID_DITHER:
  441.     case HYBRID2_DITHER:
  442.     case FS4_DITHER:
  443.     case FS2_DITHER:
  444.     case FS2FAST_DITHER:
  445.     case Twox2_DITHER:
  446.     case ORDERED_DITHER:
  447.     case ORDERED2_DITHER:
  448.     case MBORDERED_DITHER:
  449.       fprintf(stderr, "trying -dither color\n");
  450.       ditherType = FULL_COLOR_DITHER;
  451.       InitColorDisplay(name);
  452.       InitColorDither(matched_depth == 32);
  453.       return;
  454.  
  455.     case GRAY_DITHER:
  456.     case GRAY2_DITHER:
  457.     case GRAY256_DITHER:
  458.     case GRAY2562_DITHER:
  459.     case FULL_COLOR_DITHER:
  460.     case FULL_COLOR2_DITHER:
  461.     case MONO_DITHER:
  462.     case MONO_THRESHOLD:
  463.     default:
  464.       /* cant do anything */
  465.       exit(-1);
  466.   }
  467. }
  468.  
  469.   gc = XCreateGC(display, window, 0, 0);
  470.  
  471.   dcmap = cmap = XDefaultColormap(display, DefaultScreen(display));
  472.  
  473.   xcolor.flags = DoRed | DoGreen | DoBlue;
  474.  
  475.   if (owncmFlag) goto create_map;
  476.   retry_alloc_colors:
  477.   for (i=0; i<ncolors; i++) {
  478.  
  479.     lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE;
  480.     cr_num = (i / CB_RANGE)%CR_RANGE;
  481.     cb_num = i % CB_RANGE;
  482.  
  483.     ConvertColor(lum_num, cr_num, cb_num, &r, &g, &b);
  484.  
  485.     xcolor.red = r * 256;
  486.     xcolor.green = g * 256;
  487.     xcolor.blue = b * 256;
  488.  
  489.     if (XAllocColor(display, cmap, &xcolor) == 0 && cmap == dcmap) {
  490.       int j;
  491.       unsigned long tmp_pixel;
  492.       XWindowAttributes xwa;
  493.  
  494.       if (!quietFlag) {
  495.         fprintf(stderr, "Using private colormap.\n");
  496.       }
  497.  
  498.       /* Free colors. */
  499.       for(j = 0; j < i; j ++) {
  500.         tmp_pixel = wpixel[j];
  501.         XFreeColors(display, cmap, &tmp_pixel, 1, 0);
  502.       }
  503.  
  504.       create_map:
  505.       XGetWindowAttributes(display, window, &xwa);
  506.       cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
  507.       XSetWindowColormap(display, window, cmap);
  508.  
  509.       goto retry_alloc_colors;
  510.     }
  511.     pixel[i] = xcolor.pixel;
  512.     wpixel[i] = xcolor.pixel;
  513.   }
  514.  
  515.   ximage = NULL;
  516. }
  517.  
  518.  
  519. /*
  520.  *--------------------------------------------------------------
  521.  *
  522.  * InitGrayDisplay --
  523.  *
  524.  *    Initialized display for gray scale dither.
  525.  *
  526.  * Results:
  527.  *      None.
  528.  *
  529.  * Side effects:
  530.  *      None.
  531.  *
  532.  *--------------------------------------------------------------
  533.  */
  534.  
  535. void InitGrayDisplay(name)
  536. char *name;
  537. {
  538.   int ncolors = 128;
  539.   XColor xcolor;
  540.   int i;
  541.   Colormap dcmap;
  542.   unsigned long tmp_pixels[256];
  543.  
  544.   MakeWindow(name);
  545.  
  546.   gc = XCreateGC(display, window, 0, 0);
  547.  
  548.   dcmap = cmap = XDefaultColormap(display, DefaultScreen(display));
  549.  
  550.   xcolor.flags = DoRed | DoGreen | DoBlue;
  551.  
  552.   if (owncmFlag) goto create_map;
  553.   retry_alloc_grays:
  554.   for (i=0; i<ncolors; i++) {
  555.  
  556.     xcolor.red = (i*2) * 256;
  557.     xcolor.green = (i*2) * 256;
  558.     xcolor.blue = (i*2) * 256;
  559.  
  560.     if(XAllocColor(display, cmap, &xcolor) == 0 && cmap == dcmap) {
  561.       int j;
  562.       XWindowAttributes xwa;
  563.  
  564.       if (!quietFlag) {
  565.         fprintf(stderr, "Using private colormap.\n");
  566.       }
  567.  
  568.       /* Free colors. */
  569.       for(j = 0; j < i; j ++) {
  570.         unsigned long tmp_pixel;
  571.         tmp_pixel = tmp_pixels[j*2];
  572.         XFreeColors(display, cmap, &tmp_pixel, 1, 0);
  573.       }
  574.  
  575.       create_map:
  576.       XGetWindowAttributes(display, window, &xwa);
  577.       cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
  578.       XSetWindowColormap(display, window, cmap);
  579.  
  580.       goto retry_alloc_grays;
  581.     }
  582.     tmp_pixels[i*2] = pixel[i*2] = xcolor.pixel;
  583.     tmp_pixels[(i*2)+1] = pixel[(i*2)+1] = xcolor.pixel;
  584.     wpixel[(i*2)] = xcolor.pixel;
  585.     wpixel[(i*2)+1] = xcolor.pixel;
  586.     if(matched_depth == 8) {
  587.       wpixel[i*2] |= wpixel[i*2] << 8;
  588.       wpixel[i*2+1] |= wpixel[i*2+1] << 8;
  589.     }
  590.     if(matched_depth == 8 || matched_depth == 16) {
  591.       wpixel[i*2] |= wpixel[i*2] << 16;
  592.       wpixel[i*2+1] |= wpixel[i*2+1] << 16;
  593.     }
  594. #ifdef SIXTYFOUR_BIT
  595.     if(matched_depth == 8 || matched_depth == 16 || matched_depth == 24 || matched_depth == 32) {
  596.       wpixel[i*2] |= wpixel[i*2] << 32;
  597.       wpixel[i*2+1] |= wpixel[i*2+1] << 32;
  598.     }
  599. #endif
  600.  
  601.   }
  602.  
  603.   ximage = NULL;
  604. }
  605.  
  606.  
  607. /*
  608.  *--------------------------------------------------------------
  609.  *
  610.  * InitGray256Display --
  611.  *
  612.  *    Initialized display for gray scale dither with 256 levels
  613.  *
  614.  * Results:
  615.  *      None.
  616.  *
  617.  * Side effects:
  618.  *      None.
  619.  *
  620.  *--------------------------------------------------------------
  621.  */
  622.  
  623.  
  624. void InitGray256Display(name)
  625. char *name;
  626. {
  627.   int ncolors = 256;
  628.   XColor xcolor;
  629.   int i;
  630.   Colormap dcmap;
  631.   int result;
  632.   XWindowAttributes xwa;
  633.   unsigned long tmp_pixels[256];
  634.  
  635.   MakeWindow(name);
  636.  
  637.   gc = XCreateGC(display, window, 0, 0);
  638.  
  639.   dcmap = cmap = XDefaultColormap(display, DefaultScreen(display));
  640.  
  641.   xcolor.flags = DoRed | DoGreen | DoBlue;
  642.  
  643.   if (owncmFlag) {
  644.     XGetWindowAttributes(display, window, &xwa);
  645.     cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
  646.     XSetWindowColormap(display, window, cmap);
  647.   }
  648.  
  649.   retry_alloc_grays:
  650.   for (i=0; i<ncolors; i++) {
  651.     xcolor.red = i * 256;
  652.     xcolor.green = i * 256;
  653.     xcolor.blue = i * 256;
  654.     if((result=XAllocColor(display, cmap, &xcolor)) == 0 && cmap == dcmap) {
  655.       int j;
  656.       unsigned long tmp_pixel;
  657.  
  658.       if (!quietFlag) {
  659.         fprintf(stderr, "Using private colormap.\n");
  660.       }
  661.  
  662.       /* Free colors. */
  663.       for(j = 0; j < i; j ++) {
  664.         tmp_pixel = tmp_pixels[j];
  665.         XFreeColors(display, cmap, &tmp_pixel, 1, 0);
  666.       }
  667.  
  668.       XGetWindowAttributes(display, window, &xwa);
  669.       cmap = XCreateColormap(display, window, xwa.visual, AllocNone);
  670.       XSetWindowColormap(display, window, cmap);
  671.  
  672.       goto retry_alloc_grays;
  673.     }
  674.     tmp_pixels[i] = pixel[i] = xcolor.pixel;
  675.     wpixel[i] = xcolor.pixel;
  676.     if(matched_depth == 8) wpixel[i] |= wpixel[i] << 8;
  677.     if(matched_depth == 8 || matched_depth == 16) {
  678.       wpixel[i] |= wpixel[i] << 16;
  679.     }
  680. #ifdef SIXTYFOUR_BIT
  681.     if(matched_depth == 8 || matched_depth == 16 || matched_depth == 24 || matched_depth == 32) {
  682.       wpixel[i] |= wpixel[i] << 32;
  683.     }
  684. #endif
  685.  
  686.   }
  687.  
  688.   ximage = NULL;
  689. }
  690.  
  691.  
  692. /*
  693.  *--------------------------------------------------------------
  694.  *
  695.  * InitMonoDisplay --
  696.  *
  697.  *    Initialized display for monochrome dither.
  698.  *
  699.  * Results:
  700.  *      None.
  701.  *
  702.  * Side effects:
  703.  *      None.
  704.  *
  705.  *--------------------------------------------------------------
  706.  */
  707.  
  708. void InitMonoDisplay(name)
  709. char *name;
  710. {
  711.   XGCValues xgcv;
  712.  
  713.   MakeWindow(name);
  714.  
  715.   xgcv.background = BlackPixel(display, DefaultScreen(display));
  716.   xgcv.foreground = WhitePixel(display, DefaultScreen(display));
  717.  
  718.   gc = XCreateGC(display, window, GCForeground | GCBackground, &xgcv);
  719.  
  720.   ximage = NULL;
  721. }
  722.  
  723.  
  724.  
  725. /*
  726.  *--------------------------------------------------------------
  727.  *
  728.  * InitColorDisplay --
  729.  *
  730.  *    Initialized display for full color output.
  731.  *
  732.  * Results:
  733.  *      None.
  734.  *
  735.  * Side effects:
  736.  *      None.
  737.  *
  738.  *--------------------------------------------------------------
  739.  */
  740.  
  741. void InitColorDisplay(name)
  742. char *name;
  743. {
  744.   XWindowAttributes winattr;
  745.   MakeWindow(name);
  746.  
  747.   gc = XCreateGC(display, window, 0, 0);
  748.   ximage = NULL;
  749.  
  750.   XGetWindowAttributes(display, window, &winattr);
  751.   /*
  752.    * Misuse of wpixel 
  753.    */
  754.   wpixel[0] = winattr.visual->red_mask;
  755.   wpixel[1] = winattr.visual->green_mask;
  756.   wpixel[2] = winattr.visual->blue_mask;
  757. }
  758.  
  759.  
  760. /*
  761.  *--------------------------------------------------------------
  762.  *
  763.  * ExecuteDisplay --
  764.  *
  765.  *    Actually displays display plane in previously created window.
  766.  *
  767.  * Results:
  768.  *    None.
  769.  *
  770.  * Side effects:
  771.  *    None.
  772.  *
  773.  *--------------------------------------------------------------
  774.  */
  775.  
  776. void
  777. ExecuteDisplay(vid_stream)
  778.      VidStream *vid_stream;
  779. {
  780.   char dummy;
  781.   Visual *FindFullColorVisual();
  782.   Visual *fc_visual;
  783.   int depth;
  784.   static int rate_deal = -1;
  785.   static int one_frame_time;
  786.   static struct timeval tftarget, tfnow;
  787.   register int usec, sec;
  788.  
  789.   totNumFrames++;
  790.  
  791.   if (partialFlag) {
  792.     if ((endFrame != -1) && (totNumFrames > endFrame)) {
  793. #ifdef ANALYSIS
  794.       PrintAllStats();
  795. #endif
  796.       PrintTimeInfo();
  797.       
  798.       if (loopFlag) {
  799.               clear_data_stream(&vid_stream->buf_start,
  800.               &vid_stream->max_buf_length,
  801.               &vid_stream->buf_length, 
  802.               &vid_stream->buffer);
  803.               longjmp(env, 1);
  804.       }
  805.       
  806.       DestroyVidStream(curVidStream);
  807.       exit(0);
  808.     }
  809.     if (totNumFrames < startFrame) {
  810.       return;
  811.     }
  812.   }
  813.  
  814.     /* Do frame rate control */
  815.   switch (rate_deal) {
  816.   case 0:
  817.     break;
  818.   default:
  819.     gettimeofday(&tfnow, (struct timezone *)NULL);
  820.     usec = tftarget.tv_usec - tfnow.tv_usec;
  821.     sec  = tftarget.tv_sec - tfnow.tv_sec;
  822.     if (usec < 0) {
  823.       usec += 1000000;
  824.       sec--;
  825.     }
  826.     
  827.     /* If we're not behind, wait a bit */
  828.     if ((sec >= 0)  &&  usec > 0) {
  829.       tfnow.tv_sec = sec;
  830.       tfnow.tv_usec = usec;
  831.       select(0, NULL, NULL, NULL ,&tfnow); 
  832.       gettimeofday(&tfnow, (struct timezone *)NULL);
  833.     }
  834.     /* Setup target for next frame */
  835.     tftarget.tv_usec = tfnow.tv_usec + one_frame_time;
  836.     if (tftarget.tv_usec >= 1000000) {
  837.       tftarget.tv_usec -= 1000000;
  838.       tftarget.tv_sec = tfnow.tv_sec + 1;
  839.     } else tftarget.tv_sec = tfnow.tv_sec;
  840.     break;
  841.   case -1:
  842.     switch (framerate) {
  843.     case -1: /* Go with stream Value */
  844.       rate_deal = VidRateNum[vid_stream->picture_rate];
  845.       gettimeofday(&tftarget, (struct timezone *)NULL);
  846.       one_frame_time = 1000000 / rate_deal;
  847.       break;
  848.     case 0: /* as fast as possible */
  849.       rate_deal = 0;
  850.       break;
  851.     default:
  852.       rate_deal = framerate;
  853.       gettimeofday(&tftarget, (struct timezone *)NULL);
  854.       one_frame_time = 1000000 / rate_deal;
  855.       break;
  856.     }
  857.     break;
  858.   }
  859.  
  860.   if (!quietFlag) {
  861.     fprintf (stderr, "%d\r", totNumFrames);
  862.   }
  863.  
  864.  
  865.   if (requireKeypressFlag) {
  866.     char foo;
  867.     printf("Press return (%d) ",totNumFrames);    
  868.     while ((foo=getchar())!='\n');
  869.   }
  870.  
  871.   if (ditherType == NO_DITHER) return;
  872.   if (ditherType == PPM_DITHER) {
  873.     ExecutePPM(vid_stream);
  874.     return;
  875.   }
  876.   if (!noDisplayFlag) {
  877.   if (ximage == NULL) {
  878.  
  879.     int pixels_per_mb = 16;
  880.     if(IS_2x2_DITHER(ditherType)) pixels_per_mb = 32;
  881.     
  882.     if ((ditherType == FULL_COLOR_DITHER) ||
  883.            (ditherType == FULL_COLOR2_DITHER)) {
  884.       int w, h;
  885.       
  886.       w = vid_stream->mb_width  * pixels_per_mb;
  887.       h = vid_stream->mb_height * pixels_per_mb;
  888.       
  889.       fc_visual = FindFullColorVisual(display, &depth);
  890.       ximage = XCreateImage (display, fc_visual, depth, ZPixmap,
  891.                  0, &dummy, w, h, 32, 0);
  892.       
  893.     } else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) {
  894.       ximage = XCreateImage (display, None, matched_depth, XYBitmap, 0, &dummy,
  895.                  vid_stream->mb_width * pixels_per_mb,
  896.                  vid_stream->mb_height * pixels_per_mb, 8, 0);
  897.       ximage->byte_order = MSBFirst;
  898.       ximage->bitmap_bit_order = MSBFirst;
  899.     } else {
  900.       ximage = XCreateImage(display, None, matched_depth, ZPixmap, 0, &dummy,
  901.                 vid_stream->mb_width * pixels_per_mb,
  902.                 vid_stream->mb_height * pixels_per_mb, 8, 0);
  903.     }
  904.   }
  905.  
  906. /* 
  907.  * Always work in native bit and byte order. This tells Xlib to reverse
  908.  * bit and byte order if necessary when crossing a network. Frankly, this
  909.  * part of XImages is somewhat underdocumented, so this may not be exactly
  910.  * correct.
  911.  */ 
  912. #ifdef LITTLE_ENDIAN_ARCHITECTURE
  913.     ximage->byte_order = LSBFirst;
  914.     ximage->bitmap_bit_order = LSBFirst;
  915. #else
  916.     ximage->byte_order = MSBFirst;
  917.     ximage->bitmap_bit_order = MSBFirst;
  918. #endif
  919.  
  920.   
  921. #ifdef SH_MEM
  922.     if (shmemFlag) {
  923.            XShmPutImage(display, window, gc, vid_stream->current->ximage, 
  924.            0, 0, 0, 0,
  925.            vid_stream->current->ximage->width, 
  926.            vid_stream->current->ximage->height, True);
  927.            XFlush(display);
  928.       
  929.       while(1) {
  930.         XEvent xev;
  931.     
  932.         XNextEvent(display, &xev);
  933.         if (xev.type == CompletionType) {
  934.           break;
  935.         }
  936.       }
  937.     }
  938.     else 
  939. #endif
  940.       
  941.       {
  942.         ximage->data = (char *) vid_stream->current->display; 
  943.     
  944.         XPutImage(display, window, gc, ximage, 0, 0, 0, 0, ximage->width, ximage->height);
  945.       }
  946.   }
  947. }
  948.  
  949.  
  950. extern char *inputName;
  951. extern char *strrchr();
  952. #define PPM_BITS 8
  953.  
  954.  
  955. /*
  956.  *--------------------------------------------------------------
  957.  *
  958.  * ExecutePPM --
  959.  *
  960.  *    Write out a display plane as a PPM file.
  961.  *
  962.  * Results:
  963.  *    None.
  964.  *
  965.  * Side effects:
  966.  *    None.
  967.  *
  968.  *--------------------------------------------------------------
  969.  */
  970.  
  971. void
  972. ExecutePPM(vid_stream)
  973.      VidStream *vid_stream;
  974. {
  975.   static int munged = 0;
  976.   static char mungedInputName[300];
  977.   char fileName[300];
  978.   FILE *file;
  979.   int n;
  980.   unsigned int *p;
  981.   unsigned int r, g, b;
  982.  
  983.   if (!munged) {
  984.     char *cp;
  985.  
  986.     cp = strrchr(inputName, '/');
  987.     if (cp != NULL)
  988.       ++cp;
  989.     else
  990.       cp = inputName;
  991.     strcpy(mungedInputName, cp);
  992.     cp = strrchr(mungedInputName, '.');
  993.     if (cp != NULL)
  994.     *cp = '\0';
  995.     munged = 1;
  996.   }
  997.  
  998.   sprintf(fileName, "%s_%05d.ppm", mungedInputName, totNumFrames );
  999.   file = fopen(fileName, "w");
  1000.   if (file == NULL) {
  1001.     perror(fileName);
  1002.     exit(1);
  1003.   }
  1004.  
  1005.   fprintf(file, "P6\n");
  1006.   fprintf(file, "%d %d\n", vid_stream->h_size, vid_stream->v_size);
  1007.   fprintf(file, "255\n");
  1008.  
  1009.   p = (unsigned int *) vid_stream->current->display;
  1010.   n = vid_stream->h_size * vid_stream->v_size;
  1011.   while (n > 0) {
  1012.     r = *p & 0xff;
  1013.     g = (*p >> PPM_BITS) & 0xff;
  1014.     b = (*p >> (2*PPM_BITS)) & 0xff;
  1015.     putc(r, file);
  1016.     putc(g, file);
  1017.     putc(b, file);
  1018.     ++p;
  1019.     --n;
  1020.   }
  1021.  
  1022.   fclose(file);
  1023. }
  1024.  
  1025.  
  1026.